﻿using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using ProtoBuf;
using Formatting = Newtonsoft.Json.Formatting;

namespace mst_regex
{
    [ProtoContract, JsonObject(MemberSerialization.OptIn)]
    public class DailyMarketStatistics : IPersistable
    {
        public DailyMarketStatistics(StockExchangeType stockExchange, DateTime effectiveDate)
        {
            StockExchange = stockExchange;
            EffectiveDate = effectiveDate;

            PublicTransactions = new StockPositions();
            SpotTransactions = new StockPositions();
            OddlotTransactions = new OddlotStockPositions();
        }

        public DailyMarketStatistics()
        {
            PublicTransactions = new StockPositions();
            SpotTransactions = new StockPositions();
            OddlotTransactions = new OddlotStockPositions();
        }

        [JsonProperty, JsonConverter(typeof (JavaScriptDateTimeConverter)), XmlElement(DataType = "date"),
         ProtoMember(1)]
        public DateTime EffectiveDate { get; set; }

        [JsonProperty, DefaultValue(StockExchangeType.Dse)]
        public StockExchangeType StockExchange { get; set; }

        [ProtoMember(2)]
        int StockExchangeShim
        {
            get { return (int) StockExchange; }
            set { StockExchange = (StockExchangeType) value; }
        }

        [JsonProperty, ProtoMember(3)]
        public decimal DsiOpen { get; set; }

        [JsonProperty, ProtoMember(4)]
        public decimal DsiClose { get; set; }

        [JsonProperty, ProtoMember(5)]
        public decimal DsiChangeInPoints { get; set; }

        [JsonProperty, ProtoMember(6)]
        public decimal DsiChangeInPercents { get; set; }

        [JsonProperty, ProtoMember(7)]
        public decimal DgenOpen { get; set; }

        [JsonProperty, ProtoMember(8)]
        public decimal DgenClose { get; set; }

        [JsonProperty, ProtoMember(9)]
        public decimal DgenChangeInPoints { get; set; }

        [JsonProperty, ProtoMember(10)]
        public decimal DgenChangeInPercents { get; set; }

        [JsonProperty, ProtoMember(11)]
        public decimal Ds20Open { get; set; }

        [JsonProperty, ProtoMember(12)]
        public decimal Ds20Close { get; set; }

        [JsonProperty, ProtoMember(13)]
        public decimal Ds20ChangeInPoints { get; set; }

        [JsonProperty, ProtoMember(14)]
        public decimal Ds20ChangeInPercents { get; set; }

        [JsonProperty, ProtoMember(15)]
        public int Trades { get; set; }

        [JsonProperty, ProtoMember(16)]
        public int Volume { get; set; }

        [JsonProperty(PropertyName = "Value"), XmlElement(ElementName = "Value"), ProtoMember(17, Name = "Value")]
        public decimal ValueInMillions { get; set; }

        [JsonProperty, ProtoMember(18)]
        public decimal MarketCapEquity { get; set; }

        [JsonProperty, ProtoMember(19)]
        public decimal MarketCapMutualFunds { get; set; }

        [JsonProperty, ProtoMember(20)]
        public decimal MarketCapDebt { get; set; }

        [JsonProperty, ProtoMember(21)]
        public decimal MarketCapTotal { get; set; }

        [JsonProperty, ProtoMember(22)]
        public StockPositions PublicTransactions { get; private set; }

        //[JsonProperty, ProtoMember(23)]
        public StockPositions SpotTransactions { get; private set; }

        //[JsonProperty, ProtoMember(24)]
        public OddlotStockPositions OddlotTransactions { get; private set; }

        #region IPersistable Members

        public string ToCsv()
        {
            throw new NotImplementedException();
        }

        public string ToXml()
        {
            string xmlString = null;
            try
            {
                using (var stream = new MemoryStream())
                {
                    var settings = new XmlWriterSettings
                                       {
                                           Indent = GlobalOptions.Instance.IndentSerializedOutput,
                                           OmitXmlDeclaration = true,
                                           Encoding = Encoding.UTF8,
                                           ConformanceLevel = ConformanceLevel.Auto
                                       };

                    using (XmlWriter writer = XmlWriter.Create(stream, settings))
                    {
                        var serializer = new XmlSerializer(typeof (DailyMarketStatistics));
                        serializer.Serialize(writer, this);
                        writer.Flush();
                    }
                    xmlString = Encoding.Default.GetString(stream.ToArray());
                }
            }
            catch
            {
            }

            return xmlString;
        }

        public string ToJson()
        {
            return JsonConvert.SerializeObject(this,
                                               GlobalOptions.Instance.IndentSerializedOutput
                                                   ? Formatting.Indented
                                                   : Formatting.None);
        }

        public byte[] ToProtobuf()
        {
            byte[] proto;
            using (var stream = new MemoryStream())
            {
                Serializer.Serialize(stream, this);
                proto = stream.ToArray();
            }

            return proto;
        }

        public IPersistable FromCsv(string csv, bool containsHeader)
        {
            throw new NotImplementedException();
        }

        IPersistable IPersistable.FromXml(string xml)
        {
            return FromXml(xml);
        }

        IPersistable IPersistable.FromJson(string json)
        {
            return FromJson(json);
        }

        IPersistable IPersistable.FromProtobuf(byte[] proto)
        {
            return FromProtobuf(proto);
        }

        #endregion

        public static DailyMarketStatistics FromXml(string xml)
        {
            DailyMarketStatistics obj = null;
            using (var stringReader = new StringReader(xml))
            {
                using (var xmlReader = new XmlTextReader(stringReader))
                {
                    var serializer = new XmlSerializer(typeof (DailyMarketStatistics));
                    obj = (DailyMarketStatistics) serializer.Deserialize(xmlReader);
                }
            }
            return obj;
        }

        public static DailyMarketStatistics FromJson(string json)
        {
            return JsonConvert.DeserializeObject<DailyMarketStatistics>(json);
        }

        public static DailyMarketStatistics FromProtobuf(byte[] proto)
        {
            using (var stream = new MemoryStream())
            {
                stream.Write(proto, 0, proto.Length);
                stream.Seek(0, SeekOrigin.Begin);

                return Serializer.Deserialize<DailyMarketStatistics>(stream);
            }
        }

        public void SetIndexValues(string indexTitle, decimal indexValue, decimal changePts, decimal changePcts)
        {
            switch (indexTitle.ToUpper())
            {
                case @"DSI":
                    DsiClose = indexValue;
                    DsiChangeInPoints = changePts;
                    DsiChangeInPercents = changePcts;
                    break;
                case "DS20":
                    Ds20Close = indexValue;
                    Ds20ChangeInPoints = changePts;
                    Ds20ChangeInPercents = changePcts;
                    break;
                case "DGEN":
                    DgenClose = indexValue;
                    DgenChangeInPoints = changePts;
                    DgenChangeInPercents = changePcts;
                    break;
            }
        }
    }
}